package com.atguigu.gmall.service.config;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.service.entity.GmallCorrelationData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
@Slf4j
public class MQProducerAckConfig implements RabbitTemplate.ConfirmCallback,
        RabbitTemplate.ReturnCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct  //初始化注解 按顺序加载
    public void MQProducerAckConfig(){
        this.rabbitTemplate.setConfirmCallback(this);
        this.rabbitTemplate.setReturnCallback(this);
    }

    //交换机应答方法
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {

        if (ack) {
            log.info("交换机应答成功" + cause);
        } else {
            log.info("交换机应答成功" + cause);
            retryMessage(correlationData);
        }
    }

    //重新发送消息
    private void retryMessage(CorrelationData correlationData) {
        GmallCorrelationData correlationData1 = (GmallCorrelationData) correlationData;
        //重新发三次 仍不成功 则写日志
        int retryCount = correlationData1.getRetryCount();
        if (retryCount<3){
            retryCount ++;
            correlationData1.setRetryCount(retryCount);
            System.out.println("重新发送第" + retryCount + "次");
            //更新缓存中的发送次数
            String cacheKey = "mq:retry:message";
            redisTemplate.opsForHash().put(cacheKey,correlationData1.getId(),
                    JSONObject.toJSONString(correlationData1));
            //重新发送
            rabbitTemplate.convertAndSend(correlationData1.getExchange(),
                    correlationData1.getRoutingKey(),correlationData1.getMessage(),
                    correlationData1);
        }else {
            log.error("重新发送3次仍然失败：" +
                    JSONObject.toJSONString(correlationData1));
        }
    }

    //队列应答方法
    @Override
    public void returnedMessage(Message message,
                                int replyCode,
                                String replyText,
                                String exchange,
                                String routingKey) {
        log.info("队列应答失败：" + exchange + ":" + routingKey);
        log.info("队列应答失败：" + replyCode + ":" + replyText);

        Object uuid = message.getMessageProperties().
                getHeaders().get("spring_returned_message_correlation");
        String cacheKey = "mq:retry:message";
        String json = (String) redisTemplate.opsForHash().get(cacheKey, uuid);
        GmallCorrelationData correlationData =
                JSONObject.parseObject(json, GmallCorrelationData.class);
        //判断是否是基于插件的延迟消息  不要丢弃
        if (correlationData.isChajian()){
            System.out.println("基于插件的暂时不重发了");
            return;
        }
        //重新发送
        retryMessage(correlationData);
    }

    @Autowired
    private RedisTemplate redisTemplate;

}
